/*
@Time: 2025/9/22 21:42
@Author: Leslie
@Function: 时间工具类
*/

package utils

import (
	"database/sql/driver"
	"fmt"
	"time"
)

var (
	formatTime = "2006-01-02 15:04:05" // 统一时间格式
)

type HTime struct {
	time.Time
}

// MarshalJSON JSON序列化：接收者用指针（避免值拷贝，且能处理nil）
func (t *HTime) MarshalJSON() ([]byte, error) {
	if t == nil || t.Time.IsZero() {
		return []byte("null"), nil // 空时间返回null，避免JSON格式错误
	}
	formatted := fmt.Sprintf("\"%s\"", t.Format(formatTime))
	return []byte(formatted), nil
}

// UnmarshalJSON JSON反序列化：接收者必须用指针（需要修改内部值）
func (t *HTime) UnmarshalJSON(data []byte) (err error) {
	if string(data) == "null" {
		t.Time = time.Time{} // 处理null值，设为零时间
		return nil
	}
	// 解析JSON中的时间字符串（包含前后双引号）
	now, err := time.ParseInLocation(`"`+formatTime+`"`, string(data), time.Local)
	if err != nil {
		return fmt.Errorf("unmarshal JSON time failed: %v, err: %w", string(data), err)
	}
	t.Time = now
	return nil
}

// Value 写入数据库：接收者用值类型（实现 driver.Valuer 接口）
func (t HTime) Value() (driver.Value, error) {
	var zeroTime time.Time
	if t.Time.Equal(zeroTime) { // 用 Equal 比较时间，比 UnixNano 更严谨
		return nil, nil // 零时间返回null（根据业务需求可调整）
	}
	return t.Time, nil // 返回内部的 time.Time，数据库可识别
}

// Scan 从数据库读取：接收者用指针类型（实现 sql.Scanner 接口，需修改内部值）
func (t *HTime) Scan(v interface{}) error {
	switch value := v.(type) {
	case time.Time:
		t.Time = value
		return nil
	case []byte:
		parsedTime, err := time.ParseInLocation(formatTime, string(value), time.Local)
		if err != nil {
			return fmt.Errorf("parse []byte time failed: %v, err: %w", string(value), err)
		}
		t.Time = parsedTime
		return nil
	case string:
		parsedTime, err := time.ParseInLocation(formatTime, value, time.Local)
		if err != nil {
			return fmt.Errorf("parse string time failed: %v, err: %w", value, err)
		}
		t.Time = parsedTime
		return nil
	default:
		return fmt.Errorf("unsupported Scan type for HTime: %T (value: %v)", v, v)
	}
}
